home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
byt87ibm.arc
/
RDUNCAN.ARC
/
STAMPER.ASM
next >
Wrap
Assembly Source File
|
1987-09-27
|
16KB
|
432 lines
----------------------------------------------------------------------
The MASM source file: STAMPER.ASM
----------------------------------------------------------------------
name stamper
page 55,132
title STAMPER: a simple keyboard monitor
.286c
.sall
;
; STAMPER.EXE: a simple OS/2 monitor that inserts
; a date or time stamp into the keyboard data stream.
;
; Alt-D is the hot-key for a date-stamp.
; Alt-T is the hot-key for a time-stamp.
; Alt-X causes the STAMPER.EXE monitor to exit.
;
; Copyright (C) 1987 Ray Duncan
;
; To assemble and link this program:
;
; MASM stamper;
; LINK stamper,,,DOSCALLS,stamper;
;
; To use this program, execute it with the command:
;
; C>DETACH STAMPER
;
stdin equ 0 ; standard device handles
stdout equ 1
stderr equ 2
cr equ 0dh ; ASCII carriage return
lf equ 0ah ; ASCII line feed
; Hot-key definitions:
datekey equ 20h ; Alt-D
timekey equ 14h ; Alt-T
exitkey equ 2dh ; Alt-X
extrn DOSGETINFOSEG:far ; OS/2 API services needed
extrn DOSEXIT:far
extrn DOSSLEEP:far
extrn DOSWRITE:far
extrn DOSMONOPEN:far
extrn DOSMONCLOSE:far
extrn DOSMONREG:far
extrn DOSMONREAD:far
extrn DOSMONWRITE:far
extrn VIOPOPUP:far
extrn VIOENDPOPUP:far
extrn VIOWRTCHARSTR:far
jerr macro target ; Macro to test return code
local zero ; in AX and jump if non-zero.
or ax,ax ; Uses JMP DISP16 to avoid
jz zero ; branch out of range errors
jmp target
zero:
endm
DGROUP group _DATA
_DATA segment word public 'DATA'
popflag dw 1 ; wait for PopUp window
wlen dw ? ; receives length written
kname db '\DEV\KBD$',0 ; device name of keyboard
khandle dw 0 ; handle from DosMonOpen
gseg dw ? ; global information segment
lseg dw ? ; local information segment
scrgrp dw ? ; foreground screen group
dstr db 'mm/dd/yy',0 ; strings used by time and
tstr db 'hh:mm',0 ; date formatting routines
monin dw 128,64 dup (0) ; buffers for monitor
monout dw 128,64 dup (0)
packet db 128 dup (0) ; buffer for kbd data packet
pktlen dw ? ; length of buffer prior to read
; call, length of data after.
msg1 db cr,lf,'Start STAMPER with DETACH!',cr,lf
msg1_len equ $-msg1
msg2 db 'STAMPER utility installed!'
msg2_len equ $-msg2
msg3 db 'Alt-D to insert date stamp.'
msg3_len equ $-msg3
msg4 db 'Alt-T to insert time stamp.'
msg4_len equ $-msg4
msg5 db 'Alt-X to shut down STAMPER.'
msg5_len equ $-msg5
msg6 db 'STAMPER utility deactivated.'
msg6_len equ $-msg6
msg7 db cr,lf,'Unexpected OS/2 error',cr,lf
msg7_len equ $-msg7
_DATA ends
_TEXT segment word public 'CODE'
assume cs:_TEXT,ds:DGROUP,ss:DGROUP
main proc far ; entry point from OS/2
push ds ; get selectors for system's
push offset DGROUP:gseg ; global information segments
push ds
push offset DGROUP:lseg
call DOSGETINFOSEG ; transfer to OS/2
jerr error ; give up if can't get selectors
mov es,lseg ; get our screen group number
mov ax,es:[8] ; and make sure we are detached
cmp ax,16
je main1 ; proceed, all is well
; not run with DETACH,
; display error message...
push stderr ; handle for standard error
push ds ; address of message
push offset DGROUP:msg1
push msg1_len ; length of message
jmp error2 ; go display and exit
main1: mov es,gseg ; get foreground screen group
mov al,byte ptr es:[0018h] ; from global info segment
cbw
mov scrgrp,ax
; open monitor connection...
push ds ; address of name \DEV\KBD$
push offset DGROUP:kname
push ds ; address to receive monitor handle
push offset DGROUP:khandle
call DOSMONOPEN ; transfer to OS/2
jerr error ; give up if can't open it
; register as keyboard monitor...
push khandle ; handle from DosMonOpen
push ds ; addr of monitor input buffer
push offset DGROUP:monin
push ds ; addr of monitor output buffer
push offset DGROUP:monout
push 1 ; request front of list
push scrgrp ; screen group we are monitoring
call DOSMONREG ; transfer to OS/2
jerr error ; give up if can't register
call signon ; else announce our presence
main2: ; monitor the keyboard character
; stream; when hot key detected,
; insert the appropriate date or
; time stamp, or exit.
mov pktlen,pktlen-packet ; set max buffer length for read
; get next keyboard data packet
push ds ; address of monitor input buffer
push offset DGROUP:monin
push 0 ; wait until data available
push ds
push offset DGROUP:packet ; buffer for keyboard data packet
push ds
push offset DGROUP:pktlen ; receives length of data packet
call DOSMONREAD ; transfer to OS/2
cmp byte ptr packet+2,0 ; is this extended code?
jnz main4 ; no, just pass it on
cmp byte ptr packet+3,exitkey
jz main5 ; jump if exit hot-key
cmp byte ptr packet+3,timekey
jnz main3 ; jump if not time hot-key
cmp word ptr packet+12,0 ; discard break packets
jnz main2
call time ; insert the time stamp
jmp main2 ; discard this key
main3: ; is it datestamp hot-key?
cmp byte ptr packet+3,datekey
jnz main4 ; no, jump
cmp word ptr packet+12,0 ; discard break packets
jnz main2
call date ; insert the date stamp
jmp main2 ; discard this key
main4: ; Not hot-key, pass packet on.
push ds ; address of monitor output buffer
push offset DGROUP:monout
push ds ; address of keyboard data packet
push offset DGROUP:packet
push pktlen ; length of data packet
call DOSMONWRITE ; transfer to OS/2
jmp main2 ; wait for another packet
main5: ; hotkey for de-install detected
cmp word ptr packet+12,0 ; make sure it's Break packet
jz main2 ; if not just discard it
push khandle ; close the monitor connection
call DOSMONCLOSE
jerr error
call signoff ; announce STAMPER exit
push 1 ; terminate all threads
push 0 ; return success code
call DOSEXIT ; final exit to OS/2
main endp
error proc near ; unilateral termination
; because of unexpected error.
cmp khandle,0 ; first shut down monitor
je error1 ; if it is active
push khandle
call DOSMONCLOSE ; ignore any error codes
error1: ; write message 'Unexpected error'
push stderr ; handle for standard error device
push ds ; address of message
push offset DGROUP:msg7
push msg7_len ; length of message
error2: push ds ; receives bytes written
push offset DGROUP:wlen
call DOSWRITE ; transfer to OS/2
push 1 ; terminate all threads
push 1 ; return error code
call DOSEXIT ; final exit to OS/2
error endp
date proc near ; format and insert date stamp
mov es,gseg ; get selector for global
; read-only information segment
mov al,byte ptr es:[11h] ; convert month to ASCII
aam
add ax,'00'
xchg al,ah
mov word ptr dstr,ax
mov al,byte ptr es:[10h] ; convert day to ASCII
aam
add ax,'00'
xchg al,ah
mov word ptr dstr+3,ax
mov ax,word ptr es:[12h] ; convert year to ASCII
sub ax,1900
aam
add ax,'00'
xchg al,ah
mov word ptr dstr+6,ax
mov si,offset DGROUP:dstr ; insert date stamp string
call stuff ; into keyboard data stream
ret ; back to caller
date endp
time proc near ; format and insert time stamp
mov es,gseg ; get selector for global
; read-only information segment
mov al,byte ptr es:[8] ; convert hours to ASCII
aam
add ax,'00'
xchg al,ah
mov word ptr tstr,ax
mov al,byte ptr es:[9] ; convert minutes to ASCII
aam
add ax,'00'
xchg al,ah
mov word ptr tstr+3,ax
mov si,offset DGROUP:tstr ; insert time stamp string
call stuff ; into keyboard data stream
ret ; back to caller
time endp
stuff proc near ; insert string into keyboard
; data stream. Call with
; SI = ASCIIZ string (null
; is discarded)
; AL, SI destroyed.
stuff1: lodsb ; get next character
or al,al ; is it null?
jnz stuff2 ; no, use it
ret ; yes, exit
stuff2: mov packet+2,al ; place ASCII code into packet
; now send this character
; to the keyboard driver...
push ds ; address of monitor output buffer
push offset DGROUP:monout
push ds ; address of keyboard data packet
push offset DGROUP:packet
push pktlen ; length of data packet
call DOSMONWRITE ; transfer to OS/2
jmp stuff1 ; do another character
stuff endp
signon proc near ; use pop-up window to
; display help message
push ds ; put up PopUp window
push offset DGROUP:popflag ; (wait until available)
push 0
call VIOPOPUP
mov dx,offset DGROUP:msg2 ; message address
mov cx,msg2_len ; length
mov ax,9 ; Y coordinate
call center ; display it
mov dx,offset DGROUP:msg3 ; message address
mov cx,msg3_len ; length
mov ax,13 ; Y coordinate
call center ; display it
mov dx,offset DGROUP:msg4 ; message address
mov cx,msg4_len ; length
mov ax,15 ; Y coordinate
call center ; display it
mov dx,offset DGROUP:msg5 ; message address
mov cx,msg5_len ; length
mov ax,17 ; Y coordinate
call center ; display it
push 0 ; pause for 3 seconds
push 3000 ; (user must be quick reader!)
call DOSSLEEP
push 0 ; take down PopUp window
call VIOENDPOPUP
ret ; back to caller
signon endp
signoff proc near ; use pop-up window to
; announce exit
push ds ; put up PopUp window
push offset DGROUP:popflag ; (wait until available)
push 0
call VIOPOPUP
mov dx,offset DGROUP:msg6 ; message address
mov cx,msg6_len ; length
mov ax,12 ; Y coordinate
call center ; display it
push 0 ; pause for 1 seconds
push 1000 ; (user must not blink
call DOSSLEEP ; at wrong time...)
push 0 ; take down PopUp window
call VIOENDPOPUP
ret ; back to caller
signoff endp
center proc near ; center a message on screen
; call DX = msg offset,
; CX = length, AX = Y coordinate
push ds ; address of message
push dx
push cx ; length of message
push ax ; Y
sub cx,80 ; X=((80-length)/2)
neg cx
shr cx,1
push cx
push 0 ; VIO handle
call VIOWRTCHARSTR ; transfer to OS/2
ret ; back to caller
center endp
_TEXT ends
end main